import os
from time import time
from lib.config import Config
import serial
from serial.tools import list_ports
import threading
import queue
import socket
import time
import keyboard

"""
1、将从串口设备接收到的数据通过TCP协议上传到服务器
2、将从TCP服务器上获取到的数据发送至串口设备
"""

serial_is_open = False
serial_rec_queue = queue.Queue(0)
serial_send_queue = queue.Queue(0)
HOST = '192.168.137.1'           
TCP_PORT = 9000
config_param = {}
CONFIG_FILE_NAME = "./config.json"

SYS_DEBUG_ENABLE = True

### 将串口接收到的数据通过TCP上传至服务器端
def tcp_send_task(tcp):
    while True:
        while not serial_rec_queue.empty():
            data = serial_rec_queue.get()[1]
            if len(data)==0:
                continue
            tcp.sendall(data)
            if SYS_DEBUG_ENABLE: print(">>> Tcp Client >> TCP Server (%d)" % (len(data)))
        time.sleep(0.005)

### 将TCP接收到的数据通过串口转发出去
def tcp_rec_task(tcp):
    global serial_send_queue
    while True:
        data = tcp.recv(4096)

        if len(data)==0:
            continue

        serial_send_queue.put((tcp, data))
        if SYS_DEBUG_ENABLE: print(">>> TCP Server >> TCP Client (%d)" % (len(data)))
        time.sleep(0.005)

### 串口收发任务
def serial_task(srl):
    global serial_is_open
    global serial_rec_queue
    time.sleep(3)
    while True:
        try:
            if serial_is_open:
                if srl.readable():
                    data = srl.read(4096)
                    if len(data)>0:
                        serial_rec_queue.put((srl, data))
                        if SYS_DEBUG_ENABLE: print(">>> Serial Rec (%d)" % (len(data)))
                        #print("Serial Rec: %s" % (str(data, "UTF-8"),))
                if srl.writable():
                    #serial_send_queue.put(b'0123456789abcd\n')
                    while not serial_send_queue.empty():
                        data = serial_send_queue.get()[1]
                        if SYS_DEBUG_ENABLE: 
                            print(">>> Serial Send (%d)" % (len(data)))
                            #print("%s" % (str(data, "UTF-8"),), end='')
                        srl.write(data)
        except:
            serial_is_open = False
            print(">>> Serial read task error!!!")
        time.sleep(0.005)

### 监听按键，退出程序
def app_exit(tcp, ser):
    tcp.close()
    ser.close()
    print("Key: CTRL+X")
    os._exit(0)

if __name__ == '__main__':
    print("<...serial comm with tcp serial...>\n")

    sys_exit = False
    cfg = Config(CONFIG_FILE_NAME)
    if not cfg.read_config():
        print("Config File Error!!!")
        sys_exit = True

    config_param = cfg.get_config().copy()
    if len(config_param)<=0:   sys_exit = True
    if sys_exit:   os._exit(0)

    HOST = config_param["SIM_SERIAL_PORT"]["TCP_SERVER_HOST"]
    TCP_PORT = config_param["SIM_SERIAL_PORT"]["TCP_SERVER_PORT"]
    serial_port = config_param["SIM_SERIAL_PORT"]["PORT"]
    serial_baud = config_param["SIM_SERIAL_PORT"]["BAUD"]

    tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_client.connect((HOST, TCP_PORT))

    tcp_send_td = threading.Thread(target=tcp_send_task, args=(tcp_client,))
    tcp_rec_td = threading.Thread(target=tcp_rec_task, args=(tcp_client,))
    tcp_send_td.start()
    tcp_rec_td.start()

    print("Serial List: ")
    sps = list_ports.comports()
    for a in sps:
        print(a.name)

    ser = serial.Serial(serial_port, serial_baud, timeout=0)
    
    print("If Exit: CTRL+X")
    keyboard.add_hotkey("ctrl+x", app_exit, args=(tcp_client,ser))

    try:
        #ser.open()
        serial_is_open = True
        ser_td = threading.Thread(target=serial_task, args=(ser,))
        ser_td.start()
    except:
        ser.close()
        print("Serial Error!")
    
    while True:
        time.sleep(60)
        print("Console Clear...")
        os.system('cls')
